<?php
/**
 *+------------------
 * madong
 *+------------------
 * Copyright (c) https://gitee.com/motion-code  All rights reserved.
 *+------------------
 * Author: Mr. April (405784684@qq.com)
 *+------------------
 * Official Website: http://www.madong.tech
 */

namespace madong\think\wf\dao;

use madong\ingenious\libs\utils\ArrayHelper;
use madong\think\wf\basic\BaseDao;
use madong\think\wf\common\Util;
use madong\think\wf\model\ProcessDefine;
use madong\think\wf\model\ProcessDefineFavorite;
use think\facade\Db;
use madong\helper\DateTime;

class ProcessDefineFavoriteDao extends BaseDao
{

    protected function setModel(): string
    {
        return ProcessDefineFavorite::class;
    }

    /**
     * 获取收藏关联流程定义-待优化think-orm 不支持whereHas 所有只能通过连表方式实现 可以使用模型自定义实现优化
     *
     * @param $where
     * @param $field
     * @param $page
     * @param $limit
     * @param $order
     * @param $with
     *
     * @return array
     */
    public function getList($where = [], $field = ['*'], $page = 0, $limit = 0, $order = '', $with = []): array
    {
        // 定义前缀
        $prefixes = [
            'pf' => 'pf.',
            'pd' => 'pd.',
        ];

        // 组装条件
        $where = $this->buildWhere($where, $prefixes);

        // 定义字段
        $fields = $this->defineFields($prefixes);

        // 获取表名
        $tableNames = $this->getTableNames();

        // 获取数据链接
        $connection = Util::getConnectionConfig();

        // 执行查询
        $query = $this->buildQuery($tableNames, $fields, $where, $prefixes, $connection);

        // 总数量
        $total = $query->count();

        // 获取数据并格式化
        $data = $query->page($page, $limit)->select()->toArray();
        return [
            $this->formatResults($data),
            $total,
        ];
    }

    private function getTableNames(): array
    {
        return [
            'define'   => ProcessDefine::getTableName(),
            'favorite' => ProcessDefineFavorite::getTableName(),
        ];
    }

    private function buildQuery($tableNames, $fields, $where, $prefixes, $connection = null)
    {
        return Db::connect($connection)
            ->table($tableNames['favorite'])
            ->alias(Util::removeTrailingSubstring($prefixes['pf']))
            ->field($fields)
            ->join([$tableNames['define'] => Util::removeTrailingSubstring($prefixes['pd'])], 'pf.process_define_id = pd.id')
            ->where($where)
            ->order('pf.create_time', 'desc');
    }

    private function buildWhere(array $where, array $prefixes): array
    {
        $fmap = ArrayHelper::filterArray(ArrayHelper::paramsFilter($where, [
            ['user_id', '', '', $prefixes['pf'] . 'user_id'],
            ['process_define_id', '', '', $prefixes['pf'] . 'process_define_id'],
        ]));

        $dmap = ArrayHelper::filterArray(ArrayHelper::paramsFilter($where, [
            ['name', '', '', $prefixes['pd'] . 'name'],
            ['display_name', '', '', $prefixes['pd'] . 'display_name'],
        ]));

        return array_merge($fmap, $dmap);
    }

    private function defineFields(array $prefixes): string
    {
        $favoriteField = Util::prefixFields([
            'id', 'user_id', 'process_define_id', 'create_time', 'update_time', 'remark',
        ], $prefixes['pf']);

        $defineField = Util::prefixFields([
            'id', 'type_id', 'icon', 'name', 'display_name', 'description',
            'enabled', 'is_active', 'content', 'version', 'create_time',
            'create_user', 'update_time', 'update_user', 'delete_time',
        ], $prefixes['pd']);

        return Util::mergeFieldStrings([$favoriteField, $defineField]);
    }

    private function formatResults(array $data): array
    {
        return array_map(function ($item) {
            return [
                'id'                => $item['pf_id'],
                'user_id'           => $item['pf_user_id'],
                'process_define_id' => $item['pf_process_define_id'],
                'create_time'       => $item['pf_create_time'],
                'update_time'       => $item['pf_update_time'],
                'remark'            => $item['pf_remark'],
                'define'            => $this->formatDefine($item),
            ];
        }, $data);
    }

    private function formatDefine(array $item): array
    {
        return [
            'id'           => $item['pd_id'],
            'type_id'      => $item['pd_type_id'],
            'icon'         => $item['pd_icon'],
            'name'         => $item['pd_name'],
            'display_name' => $item['pd_display_name'],
            'description'  => $item['pd_description'],
            'enabled'      => $item['pd_enabled'],
            'is_active'    => $item['pd_is_active'],
            'content'      => Util::convertToArrayOrObject($item['pd_content'], [], true),
            'version'      => $item['pd_version'],
            'create_time'  => $item['pd_create_time'],
            'create_user'  => $item['pd_create_user'],
            'update_time'  => $item['pd_update_time'],
            'update_user'  => $item['pd_update_user'],
            'create_date'  => DateTime::timestampToString($item['pd_create_time']),
            'update_date'  => DateTime::timestampToString($item['pd_update_time']),
        ];
    }

}
